/** 
	V1.0 -D201112
	字符设备(异步双向全双工-字节流设备)
	与 协议 之间的管理连接模块！！
	
	但纯的连接关系描述and 切换模型
	
*/
#include "vPPMgm.h"
#include "Macro_DLink.h"
#include "Mode_UTest.h" // 仅未配合测试用例 打印完整信息
/*** Interior Define */

#define LLOG_ERR
#define LLOG_TICK
#define LLOG_MARK
#define LLOG
#include "llog.h"

#ifdef	CFG_SYS_MALLOC

#define L_MALLOC 	MALLOC
#define L_FREE 		MFREE

#else
	
	#ifdef	CFG_STATIC_BUF_ALLOCATE

	#define L_MALLOC 	SMalloc
	#define L_FREE(A) 	do{LLOG_ERR(); while(1); }while(0);

	#else 

	#include <stdlib.h>
	#define L_MALLOC(A) malloc(A)
	#define L_FREE(A)	free(A)

	#endif

#endif

#ifdef GDLINK_ITERATOR_DOWN

#define GDLINK_ITERATOR_DOWN(END_NODE,LAST_NODE) \
	ptmp = LAST_NODE->pNext;\
	if( (ptmp == END_NODE) || (ptmp == NULL)){\
		ptmp = NULL;\
		break;\
	}
	
#endif

/*** Interior Struct */
struct CC_vPtcl_API{
    tDLNode DNode;
    tvPort* pBindvPort;
    
	uint16_t Id;
	uint16_t State;
	
	int (*pRecoAndParser)(uint8_t ch);	// 目的是将 byteStream 转换为 PkgStream
	int (*pBindWrite)(int (*pFunc)(uint16_t ,uint8_t* ));
    int (*pCtrl)(uint16_t Cmd,uint16_t Len,uint8_t* pPara); 

};

struct CC_vPort_API{
    tDLNode DNode;
    tvPtcl* pBindvPtcl;		// 依赖，必须占用 RAM
    
	uint16_t Id;
	uint8_t State;

	// Dev提供的都是主动 的API ，没有回调API
	int (*pWrite)(uint16_t Len,uint8_t* pPkg);	// 不使用Send，意味着 并不保证数据是立刻发送的
	int (*pRead)(uint16_t RLen,uint8_t* pRBuf); // 需要上层进行周期 轮询，意味着一个CoTask
	int (*pCtrl)(uint16_t Cmd,uint16_t Len,uint8_t* pPara); 
	// Stop,Reset,Cleanbuf,Start
	
	// CoTask Var
	uint16_t RBufSz;
	uint8_t* pRBuf;
	
	// #ifdef 	CFG_SORT_TIMER
	tSTimer* pTimer;
	// #else
	// tMs RxCheckPeriodTick;	
	// tMs MarkTick;
	// #endif
	
	int (*pRxCBF)(uint8_t ch);						// 内部 变量
	
};

struct CC_vPtcl_vPort_Management{
	tvPtcl *pPtclHead;
	tvPort *pPortHead;
	uint16_t PtclCnt;
	uint16_t PortCnt;
};
/*** Global Data */

/*** Local Function Define*/

//========================//
#ifdef CFG_V_PORT //vPort

#ifdef 	CFG_SORT_TIMER
static int CoTask_vPort_Std_RxGuard(void* pPara){
	
	int ret=RET_ERR;
	
	// uint8_t RBuf[200];
	int RealNum;
	int i;
	tvPort* pObj = (tvPort*)pPara;
	if(pObj == NULL) { LLOG_ERR(); return ret;}
	if(pObj->pRead == NULL) { return ret;}
	
	//
	RealNum = pObj->pRead(pObj->RBufSz,pObj->pRBuf);
	if(RealNum){
		if(pObj->pRxCBF != NULL){
			for(i=0;i<RealNum;i++){
				pObj->pRxCBF(pObj->pRBuf[i]);
			}
		}
		else{
			Log_ShowArray("Rx",RealNum,pObj->pRBuf);
		}
	}

	return ret;
}

#endif

#define VPORT_S_CREATE		0
#define VPORT_S_BIND_W		0x01
#define VPORT_S_BIND_R		0x02
#define VPORT_S_BIND_C		0x04
#define VPORT_S_BINE_RX		0x08
#define VPORT_S_RUNING		0x10
// #define VPORT_S_STOP		0x10

static tvPort* vPort_Create(uint16_t Id,tMs PeriodTick,uint16_t RBufSz){
	
	tvPort* ptmp = NULL;
	uint8_t* pBuf = NULL;
	
	if(Id == 0)	{ LLOG_ERR(); return ptmp; }
	
	ptmp = (tvPort*)L_MALLOC(sizeof(tvPort)+RBufSz);
	if(ptmp == NULL){
		LLOG_ERR();
		return ptmp;
	}
	pBuf = (uint8_t*)ptmp;
	MEMSET((uint8_t*)ptmp,0,sizeof(tvPort));
	ptmp->Id = Id; 
	ptmp->State = VPORT_S_CREATE; 
	
	ptmp->RBufSz = RBufSz; 
	ptmp->pRBuf = &pBuf[sizeof(tvPort)];

	#ifdef 	CFG_SORT_TIMER
	do{
		tSTimer* pTimer;
		pTimer = STimer_CreateAndAdd(0, STIMER_TYP_PERIOD, PeriodTick);
		STimer_BindCBF(pTimer,CoTask_vPort_Std_RxGuard);
		STimer_BindPara(pTimer, (void*)ptmp );
		
		STimer_OnOff(pTimer,1);	
		// ptmp->State = VPORT_S_RUNING; 

		ptmp->pTimer = pTimer;
	}while(0);
	#else
	ptmp->RxCheckPeriodTick = PeriodTick; 
	#endif

	return ptmp;
}

void vPort_Show(tvPort* pObj){
	
	if(pObj == NULL)	{LLOG_ERR(); return;}
	
	LLOG("\n====\n#I vPort=[0x%x]\n",pObj);
	LLOG("#I pNext      =[0x%x]\n",pObj->DNode.pNext);
	LLOG("#I pPrev      =[0x%x]\n",pObj->DNode.pPrev);
	LLOG("#I pBindvPtcl =[0x%x]\n",pObj->pBindvPtcl);
	
	LLOG("#I Id         =[%d]\n",pObj->Id);
	LLOG("#I State      =[0x%x]\n",pObj->State);
	
	LLOG("#I pWrite     =[0x%x]\n",pObj->pWrite);
	LLOG("#I pRead      =[0x%x]\n",pObj->pRead);
	LLOG("#I pRxCBF     =[0x%x]\n",pObj->pRxCBF);
	
	#ifdef 	CFG_SORT_TIMER
	
	#else
	LLOG("#I RxCheckPeriodTick =[%d]\n",pObj->RxCheckPeriodTick);
	LLOG("#I MarkTick   =[%d]\n",pObj->MarkTick);
	#endif
	LLOG("#I RBufSz     =[%d]\n",pObj->RBufSz);
	LLOG("#I pRBuf      =[0x%x]\n",pObj->pRBuf);
	
}

static int vPort_Bind_RxCBF(tvPort* pObj,int (*pRxCBF)(uint8_t)){
	int ret = RET_ERR;
	
	if(pObj->State&VPORT_S_RUNING) { LLOG_ERR(); return ret;}
	ret = RET_OK;
	
	#ifdef CFG_UT_VPPMGM // 仅未配合测试用例 打印完整信息
	LLOG("#I Port BindRxCBF [0x%x]\n",pRxCBF);
	#endif
	
	pObj->pRxCBF = pRxCBF;
	pObj->State |= VPORT_S_BINE_RX;
	return ret;
}

static int vPort_Set_API(tvPort* pObj,const tvPortAPISet* pAPI){
	int ret = RET_ERR;
	
	if(pObj->State&VPORT_S_RUNING) { LLOG_ERR(); return ret;}
	ret = RET_OK;

	if(pAPI->pWrite != NULL){
		pObj->pWrite = pAPI->pWrite;
		pObj->State |= VPORT_S_BIND_W;		
	}
	
	if(pAPI->pRead != NULL){
		pObj->pRead = pAPI->pRead;
		pObj->State |= VPORT_S_BIND_R;		
	}

	if(pAPI->pCtrl != NULL){
		pObj->pCtrl = pAPI->pCtrl;
		pObj->State |= VPORT_S_BIND_C;		
	}
	
	return ret;
}

/* int vPort_Set_Write(tvPort* pObj,int (*pWrite)(uint16_t,uint8_t*)){
	int ret = RET_ERR;
	
	if(pObj->State&VPORT_S_RUNING) { LLOG_ERR(); return ret;}
	ret = RET_OK;
	
	pObj->pWrite = pWrite;
	pObj->State |= VPORT_S_BIND_W;
	return ret;
}

int vPort_Set_Read(tvPort* pObj,int (*pRead)(uint16_t,uint8_t*)){
	int ret = RET_ERR;
	
	if(pObj->State&VPORT_S_RUNING) { LLOG_ERR(); return ret;}
	ret = RET_OK;
	
	pObj->pRead = pRead;
	pObj->State |= VPORT_S_BIND_R;
	return ret;
}

int vPort_Set_Ctrl(tvPort* pObj,int (*pCtrl)(uint8_t,uint16_t,uint8_t*)){
	int ret = RET_ERR;
	
	if(pObj->State&VPORT_S_RUNING) { LLOG_ERR(); return ret;}
	ret = RET_OK;
	
	pObj->pCtrl = pCtrl;
	pObj->State |= VPORT_S_BIND_C;
	return ret;
}*/

#endif

#ifdef CFG_V_PTCL

#define VPTCL_S_CREATE		0x00
#define VPTCL_S_BIND_W		0x01
#define VPTCL_S_BIND_RECO	0x02
#define VPTCL_S_BIND_C		0x04
#define VPTCL_S_BINE_RX		0x08
#define VPTCL_S_RUNING		0x10

void vPtcl_Show(tvPtcl* pObj){
	
	if(pObj == NULL)	{LLOG_ERR(); return;}
	
	LLOG("\n====\n#I vPtcl=[0x%x]\n",pObj);
	LLOG("#I pNext      =[0x%x]\n",pObj->DNode.pNext);
	LLOG("#I pPrev      =[0x%x]\n",pObj->DNode.pPrev);
	LLOG("#I pBindvPort =[0x%x]\n",pObj->pBindvPort);
	
	LLOG("#I Id         =[%d]\n",pObj->Id);
	LLOG("#I State      =[%x]\n",pObj->State);
	
	LLOG("#I pRecoAndParser =[0x%x]\n",pObj->pRecoAndParser);
	LLOG("#I pBindWrite     =[0x%x]\n",pObj->pBindWrite);
	LLOG("#I pCtrl          =[0x%x]\n",pObj->pCtrl);
	// LLOG("#I pPkgParser     =[0x%x]\n",pObj->pPkgParser);

}

static tvPtcl* vPtcl_Create(uint16_t Id){
// tvPtcl* vPtcl_Create(uint16_t Id,int (*pRecoAndParser)(uint8_t ch))
	
	tvPtcl* ptmp = NULL;
	uint8_t* pBuf = NULL;
	
	if(Id == 0)	{ LLOG_ERR(); return ptmp; }
	
	ptmp = (tvPtcl*)L_MALLOC(sizeof(tvPtcl));
	if(ptmp == NULL){
		LLOG_ERR();
		return ptmp;
	}
	pBuf = (uint8_t*)ptmp;
	MEMSET((uint8_t*)ptmp,0,sizeof(tvPtcl));
	ptmp->Id = Id; 
	ptmp->State = VPTCL_S_CREATE; 
	
	// ptmp->pRecoAndParser = pRecoAndParser; 
	// ptmp->State |= VPTCL_S_BIND_RECO; 
	return ptmp;
}

static int vPtcl_Set_API(tvPtcl* pObj,const tvPtclAPISet* pAPI){
	int ret = RET_ERR;
	
	if(pObj == NULL) { LLOG_ERR(); return ret;}
	if(pAPI == NULL) { LLOG_ERR(); return ret;}
	// if(pObj->State&VPORT_S_RUNING) { LLOG_ERR(); return ret;}
	ret = RET_OK;

	if(pAPI->pRecoAndParser != NULL){
		pObj->pRecoAndParser = pAPI->pRecoAndParser;
		pObj->State |= VPTCL_S_BIND_RECO;		
	}
	
	if(pAPI->pBindWrite != NULL){
		pObj->pBindWrite = pAPI->pBindWrite;
		pObj->State |= VPTCL_S_BIND_W;		
	}

	if(pAPI->pCtrl != NULL){
		pObj->pCtrl = pAPI->pCtrl;
		pObj->State |= VPTCL_S_BIND_C;		
	}
	
	return ret;
}

/*
int vPtcl_Set_Reco(tvPtcl* pObj,int (*pRecoAndParser)(uint8_t ch)){
	int ret = RET_ERR;
	
	if(pObj == NULL) { LLOG_ERR(); return ret;}
	// if(pObj->State&VPTCL_S_RUNING) { LLOG_ERR(); return ret;}
	ret = RET_OK;
	
	pObj->pRecoAndParser = pRecoAndParser;
	pObj->State |= VPTCL_S_BIND_RECO;
	return ret;
}

int vPtcl_Set_BindWrite(tvPtcl* pObj,int (*pBindWrite)(uint16_t,uint8_t*)){
	int ret = RET_ERR;
	
	if(pObj == NULL) { LLOG_ERR(); return ret;}
	// if(pObj->State&VPTCL_S_RUNING) { LLOG_ERR(); return ret;}
	ret = RET_OK;
	
	pObj->pBindWrite = pBindWrite;
	pObj->State |= VPTCL_S_BIND_W;
	return ret;
}

int vPtcl_Set_Ctrl(tvPtcl* pObj,int (*pCtrl)(uint8_t,uint16_t,uint8_t*)){
	int ret = RET_ERR;
	
	if(pObj == NULL) { LLOG_ERR(); return ret;}
	// if(pObj->State&VPTCL_S_RUNING) { LLOG_ERR(); return ret;}
	ret = RET_OK;
	
	pObj->pCtrl = pCtrl;
	pObj->State |= VPTCL_S_BIND_C;
	return ret;
}
*/

#endif

#ifdef CFG_VPORT_VPTCL_MGM
tvPPMgm* vPPMgm_Create(uint16_t Id){
	
	tvPPMgm* ptmp = NULL;
	uint8_t* pBuf = NULL;
	
	if(Id == 0)	{ LLOG_ERR(); return ptmp; }
	
	ptmp = (tvPPMgm*)L_MALLOC(sizeof(tvPPMgm));
	if(ptmp == NULL){
		LLOG_ERR();
		return ptmp;
	}
	MEMSET((uint8_t*)ptmp,0,sizeof(tvPPMgm));
	// ptmp->Id = Id; 
	return ptmp;
}

static int vPPMgm_AddvPtclToLink(tvPPMgm* pObj,tvPtcl* pTarget){
	//
	int ret = RET_ERR;
	
	tDLNode* pHead;
    tDLNode* ptmp;
    tDLNode* pAddNode;
	
	if(pObj == NULL) 		{ LLOG_ERR(); return ret;}
	if(pAddNode	== NULL) 	{ LLOG_ERR(); return ret;}
	
	pHead = (tDLNode*)(pObj->pPtclHead);
	pAddNode = &pTarget->DNode;
	
	ret = RET_OK;
    if(pHead == NULL){ 
		GDLNODE_INSERT_LOOPHEAD(pHead,pAddNode);
		
		pObj->pPtclHead = (tvPtcl*)pHead;
		pObj->PtclCnt++;
		return ret;
	}
	ptmp = pHead;
	GDLNODE_INSERT_BEFORE(pHead,ptmp,pAddNode);
	
	pObj->pPtclHead = (tvPtcl*)pHead;
	pObj->PtclCnt++;
	
	return ret;
}

static int vPPMgm_RemovevPtclFormLink(tvPPMgm* pObj,tvPtcl* pTarget){
	// 
	int ret = RET_ERR;
	
	tDLNode* pHead;
    tDLNode* ptmp = NULL;
    tDLNode* pRemoveNode = NULL;
	
	if(pObj == NULL) 			{ LLOG_ERR(); return ret;}
	if(pObj->pPtclHead == NULL) 	{ LLOG_ERR(); return ret;}
	if(pTarget == NULL) 			{ LLOG_ERR(); return ret;}
	
	pHead = (tDLNode*)(pObj->pPtclHead);
	
	pRemoveNode = &pTarget->DNode;
    ptmp = pHead;
    while(1){
		
        if( pRemoveNode == ptmp){ // Check_IsDLinkNode
            break;
        } 
		
		GDLINK_ITERATOR_DOWN(pHead,ptmp); 
	}
	
    if(ptmp != NULL){
		
		GDLNODE_REMOVE(pHead,ptmp);
		
		pObj->pPtclHead = (tvPtcl*)pHead;
		if(pObj->PtclCnt > 0){
			pObj->PtclCnt--;
		}
		else{
			LLOG_ERR();
		}
		ret=RET_OK;
	}	
	
	return ret;
}

static tvPtcl* vPPMgm_vPtcl_SearchByID(tvPPMgm* pObj,uint16_t ID){

    tDLNode* pHead;
	tDLNode* ptmp = NULL;
	
	if(pObj == NULL) 				{ LLOG_ERR(); return NULL;}
	if(ID == 0) 					{ LLOG_ERR(); return NULL;}
	if(pObj->pPtclHead == NULL) 	{ LLOG_ERR(); return NULL;}	

    pHead = (tDLNode*)(pObj->pPtclHead);
    ptmp = pHead;
    while(1){
        if( ((tvPtcl*)ptmp)->Id == ID){
            break;
        }
		
		GDLINK_ITERATOR_DOWN(pHead,ptmp);
    }
    return (tvPtcl*)ptmp;    
}

//
static int vPPMgm_AddvPortToLink(tvPPMgm* pObj,tvPort* pTarget){
	//
	int ret = RET_ERR;
	
	tDLNode* pHead;
    tDLNode* ptmp;
    tDLNode* pAddNode;
	
	if(pObj == NULL) 		{ LLOG_ERR(); return ret;}
	if(pAddNode	== NULL) 	{ LLOG_ERR(); return ret;}
	
	pHead = (tDLNode*)pObj->pPortHead;
	pAddNode = &pTarget->DNode;
	
	ret=RET_OK;
    if(pHead == NULL){ 
		GDLNODE_INSERT_LOOPHEAD(pHead,pAddNode);
		
		pObj->pPortHead = (tvPort*)pHead;
		pObj->PortCnt++;
		return ret;
	}   
    
	ptmp = pHead;
	GDLNODE_INSERT_BEFORE(pHead,ptmp,pAddNode);
	
	pObj->pPortHead = (tvPort*)pHead;
	pObj->PortCnt++;
	
	return ret;
}

static int vPPMgm_RemovevPortFormLink(tvPPMgm* pObj,tvPort* pTarget){
	// 
	int ret = RET_ERR;
	
	tDLNode* pHead;
    tDLNode* ptmp = NULL;
    tDLNode* pRemoveNode = NULL;
	
	if(pObj == NULL) 			{ LLOG_ERR(); return ret;}
	if(pObj->pPortHead == NULL)	{ LLOG_ERR(); return ret;}
	if(pTarget == NULL)			{ LLOG_ERR(); return ret;}
	
	pHead = (tDLNode*)pObj->pPortHead;
	
	pRemoveNode = &pTarget->DNode;
    ptmp = (tDLNode*)pObj->pPortHead;
    while(1){
		
        if( pRemoveNode == ptmp){ // Check_IsDLinkNode
            break;
        } 
		
		GDLINK_ITERATOR_DOWN(pHead,ptmp); 
	}
	
    if(ptmp != NULL){
		
		GDLNODE_REMOVE(pHead,ptmp);
		
		pObj->pPortHead = (tvPort*)pHead;
		if(pObj->PortCnt > 0){
			pObj->PortCnt--;
		}
		else{
			LLOG_ERR();
		}
		ret=RET_OK;
	}	
	
	return ret;
}

static tvPort* vPPMgm_vPort_SearchByID(tvPPMgm* pObj,uint16_t ID){

    tDLNode* ptmp = NULL;
	tDLNode* pHead;
	
	if(pObj == NULL) 				{ LLOG_ERR(); return NULL;}
	if(ID == 0) 					{ LLOG_ERR(); return NULL;}
	if(pObj->pPortHead == NULL) 	{ LLOG_ERR(); return NULL;}	

    pHead = (tDLNode*)(pObj->pPortHead);
    ptmp = pHead;
    while(1){
        if( ((tvPort*)ptmp)->Id == ID){
            break;
        }
		
		GDLINK_ITERATOR_DOWN(pHead,ptmp); 
    }
    return (tvPort*)ptmp;    
}

//
#define CHECK_EXECUTE_RET() if(ret == RET_ERR)	{LLOG_ERR(); return ret;}

static int vPPMgm_DisConnectByPtcl(tvPtcl* pPtcl){
	int ret = RET_ERR;
	
	if(pPtcl == NULL) 				{LLOG_ERR(); return RET_ERR;}
	if(pPtcl->pCtrl == NULL) 		{LLOG_ERR(); return RET_ERR;}
	if(pPtcl->pBindWrite == NULL) 	{LLOG_ERR(); return RET_ERR;}
	
	// Unbind Ptcl 
	ret = pPtcl->pCtrl(GCMD_STOP,0,NULL);
	CHECK_EXECUTE_RET();
	
	ret = pPtcl->pBindWrite(NULL);
	CHECK_EXECUTE_RET();
	
	if(pPtcl->pBindvPort != NULL){
		if(pPtcl->pBindvPort->pCtrl == NULL) {LLOG_ERR(); return RET_ERR;}
		
		ret = pPtcl->pBindvPort->pCtrl(GCMD_STOP,0,NULL);
		CHECK_EXECUTE_RET();
		
		ret = vPort_Bind_RxCBF(pPtcl->pBindvPort,NULL);
		
		// ret = pPtcl->pBindvPort->pCtrl(GCMD_CLEAN,0,NULL);
		// CHECK_EXECUTE_RET();
		
		pPtcl->pBindvPort->pBindvPtcl = NULL;
		pPtcl->pBindvPort = NULL;
	}

	ret = pPtcl->pCtrl(GCMD_CLEAN,0,NULL);
	CHECK_EXECUTE_RET();
	
	// ret=RET_OK;
	return ret;
}

static int vPPMgm_DisConnectByPort(tvPort* pPort){
	int ret = RET_ERR;
	
	if(pPort == NULL) {LLOG_ERR(); return RET_ERR;}
	if(pPort->pCtrl == NULL) {LLOG_ERR(); return RET_ERR;}
	
	// Unbind Port
	ret = pPort->pCtrl(GCMD_STOP,0,NULL);
	CHECK_EXECUTE_RET();
	
	ret = vPort_Bind_RxCBF(pPort,NULL);
	CHECK_EXECUTE_RET();
	
	if(pPort->pBindvPtcl != NULL){
		
		if(pPort->pBindvPtcl->pCtrl == NULL) {LLOG_ERR(); return RET_ERR;}
		
		ret = pPort->pBindvPtcl->pCtrl(GCMD_STOP,0,NULL);
		CHECK_EXECUTE_RET();	

		ret = pPort->pBindvPtcl->pBindWrite(NULL);
		CHECK_EXECUTE_RET();
		
		// ret = pPort->pBindvPtcl->pCtrl(GCMD_CLEAN,0,NULL);
		// CHECK_EXECUTE_RET();	
		
		pPort->pBindvPtcl->pBindvPort = NULL;
		pPort->pBindvPtcl = NULL;
	}
	
	ret = pPort->pCtrl(GCMD_CLEAN,0,NULL);
	CHECK_EXECUTE_RET();		
	
	// ret=RET_OK;
	return ret;
}

static int vPPMgm_ConnectAndStart(tvPtcl* pPtcl,tvPort* pPort){
	int ret = RET_ERR;
	
	// if(pPtcl == NULL) {LLOG_ERR(); return ret;}
	// if(pPort == NULL) {LLOG_ERR(); return ret;}
	// if(pPtcl->pCtrl == NULL) {LLOG_ERR(); return ret;}
	// if(pPort->pCtrl == NULL) {LLOG_ERR(); return ret;}
	// if(pPtcl->pBindWrite == NULL) {LLOG_ERR(); return ret;}
			
	// Bind Ptcl And Port 
	ret = pPtcl->pBindWrite(pPort->pWrite);
	CHECK_EXECUTE_RET();
	pPtcl->pBindvPort = pPort;
	
	ret = vPort_Bind_RxCBF(pPort,pPtcl->pRecoAndParser);
	CHECK_EXECUTE_RET();
	pPort->pBindvPtcl = pPtcl;
	
	ret = pPtcl->pCtrl(GCMD_START,0,NULL);
	CHECK_EXECUTE_RET();	
	ret = pPort->pCtrl(GCMD_START,0,NULL);
	CHECK_EXECUTE_RET();	
	
	ret=RET_OK;
	return ret;
}

int vPPMgm_SwitchConnect(tvPPMgm* pObj,uint16_t PtclID,uint16_t PortID){
	
	int ret = RET_ERR;
	tvPtcl* pPtcl = NULL;
	tvPort* pPort = NULL;

	pPtcl = vPPMgm_vPtcl_SearchByID(pObj,PtclID);
	if(pPtcl == NULL) {LLOG_ERR(); return RET_ERR;}
	
	pPort = vPPMgm_vPort_SearchByID(pObj,PortID);
	if(pPort == NULL) {LLOG_ERR(); return RET_ERR;}
	
	if((pPort->pBindvPtcl != NULL) && (pPtcl->pBindvPort != NULL)) {
		if( (pPort->pBindvPtcl == pPtcl) && (pPtcl->pBindvPort == pPort)) {
			LLOG("#I Already Binded\n");
			return ret;
		}
	}
	//
	ret = vPPMgm_DisConnectByPtcl(pPtcl);
	CHECK_EXECUTE_RET();
	ret = vPPMgm_DisConnectByPort(pPort);
	CHECK_EXECUTE_RET();
	ret = vPPMgm_ConnectAndStart(pPtcl,pPort);
	CHECK_EXECUTE_RET();
	
	return ret;
}

#endif 

#ifdef CFG_VPORT_VPTCL_MGM // API 整合 
tvPtcl* vPPMgm_CreatePtclAndAdd(tvPPMgm* pObj,uint16_t Id,const tvPtclAPISet* pAPI){
	
	tvPtcl* ptmp = NULL;

	if(pAPI == NULL) { LLOG_ERR(); return ptmp;}

	ptmp = vPtcl_Create(Id);
	if (ptmp == NULL) {LLOG_ERR();return ptmp;}
	
	vPtcl_Set_API(ptmp,pAPI);
	if ( RET_ERR == vPPMgm_AddvPtclToLink(pObj,ptmp) ) {
		LLOG_ERR();
	}
	return ptmp;
}

tvPort* vPPMgm_CreatePortAndAdd(tvPPMgm* pObj,uint16_t Id,const tvPortAPISet* pAPI,\
	tMs PeriodTick,uint16_t RBufSz	){
	
	tvPort* ptmp = NULL;

	if (pAPI == NULL) { LLOG_ERR(); return ptmp;}

	ptmp = vPort_Create(Id,PeriodTick,RBufSz);
	if (ptmp == NULL) { LLOG_ERR(); return ptmp;}
	
	vPort_Set_API(ptmp,pAPI);
	if (RET_ERR == vPPMgm_AddvPortToLink(pObj,ptmp) ){
		LLOG_ERR();
	}
	return ptmp;
}

#endif

